package it.antonio.ilpizze.assertion.concrete;

import it.antonio.ilpizze.assertion.Assertion;
import it.antonio.ilpizze.assertion.Condition;

import java.util.Collection;

public class CollectionAssertion<T> extends Assertion<Collection<T>> {

	public CollectionAssertion(Collection<T> instance) {
		super(instance);
		description("List");
	}

	@Override
	public CollectionAssertion<T> as(String description) {
		description(description);
		return this;
	}

	@Override
	public CollectionAssertion<T> doesNotSatisfy(Condition condition) {
		assertNotSatisfy(condition);
		return this;
	}

	@Override
	public CollectionAssertion<T> isEqualTo(Collection<T> expected) {
		assertEqual(expected);
		return null;
	}

	@Override
	public CollectionAssertion<T> isNotEqualTo(Collection<T> other) {
		assertNotEqual(other);
		return null;
	}

	@Override
	public CollectionAssertion<T> isNotNull() {
		assertNotNull();
		return null;
	}

	@Override
	public CollectionAssertion<T> isNotSameAs(Collection<T> other) {
		assertIsNotSameAs(other);
		return null;
	}

	@Override
	public CollectionAssertion<T> isSameAs(Collection<T> expected) {
		assertIsSameAs(expected);
		return null;
	}

	@Override
	public CollectionAssertion<T> satisfies(Condition condition) {
		assertSatisfy(condition);
		return null;
	}

	public CollectionAssertion<T> hasSize(int expectedSize) {
		int currentSize = instance.size();
		if (currentSize == expectedSize)
			return this;
		fail("current size:" + currentSize+  "; expected: " + expectedSize);
		return this;
	}

	public CollectionAssertion<T> contains(T... args) {
		for (Object o : args) {
			if (!instance.contains(o)) {
				fail("does not contains one of the objects you passed");
			}
		}
		return this;
	}
	public CollectionAssertion<T> notContains(T... args) {
		for (Object o : args) {
			if (instance.contains(o)) {
				fail("contains one of the objects you passed");
			}
		}
		return this;
	}

	public CollectionAssertion<T> equalElements(T... args) {
		Object[] iArray = instance.toArray();
		
		// same length
		if(iArray.length != args.length) fail("different elements");
		
		for (int i = 0; i < args.length; i++) {
			if (!iArray[i].equals(args[i])) {
				fail("different elements");
			}
		}
		return this;
	}

	@SuppressWarnings("unchecked")
	public CollectionAssertion<T> equalElements(Collection<T> elements) {
		return equalElements((T[]) elements.toArray());
	}

	public CollectionAssertion<T> isEmpty() {
		if (instance.isEmpty())
			return this;
		fail("is not empty");
		return this;
	}

	public CollectionAssertion<T> isNotEmpty() {
		if (!instance.isEmpty())
			return this;
		fail("is empty");
		return this;
	}

}